<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../ref-object/ref-object.html">
<script>
  var GIVe = (function (give) {
    /**
     * Behavior that allows to choose reference from its name.
     *
     * When the requested reference is not available (for example, needs to be
     * loaded from some external sources), the request will be queued so that
     * it can be executed when the references are ready.
     *
     * @polymerBehavior RefEmbeddedBehavior
     */
    give.RefEmbeddedBehavior = {
      properties: {
        /**
         * The reference used in the embedded browser.
         * Reference names needs to be in UCSC format.
         * Please see [GIVe.RefObject](../ref-object/)
         * to see available references on GIVe server.
         */
        ref: {
          type: String,
          observer: '_refChanged'
        },

        /**
         * The GIVe.RefObject for reference.
         * Contains chromosomal layout and track information.
         * @type {GIVe.RefObject}
         */
        _refObj: {
          type: Object
        },

        /**
         * Whether this object needs a reference with valid `chromInfo`.
         */
        needsChromInfo: {
          type: Boolean,
          value: true
        }
      },

      /**
       * The observer function to handle changes in `this.ref`.
       *
       * @param  {string} newValue - new reference name
       * @param  {string} oldValue - old reference name
       */
      _refChanged: function (newValue, oldValue) {
        this.setRef(newValue)
      },

      /**
       * Get the current reference of the element.
       *
       * @return {GIVe.RefObject}  reference currently used.
       */
      getRef: function () {
        return this._refObj
      },

      /**
       * Set the reference to new reference.
       *
       * this will reset all tracks and redo the ref
       * note that the tracks should already be initialized before switching here
       * After this, this.changeAllViewWindows should be called.
       *
       * If references are not ready (for example, need to be populated from a
       * server), `this._setRefAfterReadyCheck` will be called
       * after they are ready.
       *
       * @param  {string|GIVe.RefObject} newRef - New Reference, either name or GIVe.RefObject
       */
      setRef: function (ref, callback) {
        if (ref) {
          give.RefObject.callOnRefReady(this._setRefAfterReadyCheck.bind(
            this, ref, callback))
        }
      },

      /**
       * _setRefAfterReadyCheck - The function actually called after
       * the references are ready.
       *
       * @param  {string|GIVe.RefObject} ref - the reference name or reference object
       */
      _setRefAfterReadyCheck: function (ref, callback) {
        try {
          var refObj = give.RefObject.findRefByDb(ref)
          if (!this._refObj || this._refObj.db !== refObj.db) {
            if (!this.needsChromInfo || refObj.chromInfo) {
              // reference has been changed, needs to switch
              this._setRefObj(refObj)
              if (typeof callback === 'function') {
                callback.call(this)
              }
            } else {
              this.ref = ''
              throw new Error()
            }
          } else if (typeof callback === 'function') {
            callback.call(this)
          }
        } catch (err) {
          give._verboseConsole(err, give.VERBOSE_DEBUG, 'RefEmbeddedBehavior(' +
            this.id + ')')
          // call UI warning procedures in the future
          give.fireSignal('warning', { msg: err.message || err })
        }
      },

      /**
       * Simple function to set reference directly.
       *
       * @param  {GIVe.RefObject} refObj the reference object
       */
      _setRefObj: function (refObj) {
        this._refObj = refObj
      }
    }

    return give
  })(GIVe || {})

</script>
